package match

import (
	"sanguo/cluster"
	"sanguo/node/common/mutilCall"
	"sanguo/node/common/transaction"
	"sanguo/node/node_team"
	"sanguo/node/node_team/com"
	"sanguo/node/node_team/team"
	cs_msg "sanguo/protocol/cs/message"
	ss_msg "sanguo/protocol/ss/message"
	ss_rpc "sanguo/protocol/ss/rpc"

	"github.com/golang/protobuf/proto"
	"github.com/sniperHW/kendynet"
)

const (
	match_req    = 1
	match_cancel = 2
)

func onMatch(session kendynet.StreamSession, msg proto.Message) {
	arg := msg.(*ss_msg.Match)
	node_team.Debugln("OnCall Match", arg)

	if arg.GetMsgType() == match_req {
		_matchObj := MatchMgr.RoleToObj[arg.GetRoleID()]
		_room := MatchMgr.RoleToRoom[arg.GetRoleID()]
		if _matchObj != nil || _room != nil {
			resp := &cs_msg.MatchToC{
				MsgType: cs_msg.MatchType(cs_msg.MatchType_Matching).Enum(),
			}
			com.SendToClient(cluster.PeerID(arg.GetGame()), arg.GetUserID(), resp)
			return
		}

		nodeId, err := com.MatchGenID()
		if err != nil {
			node_team.Infoln(err)
			return
		}

		if arg.GetTeamID() == 0 { //本身没有队伍
			obj := &Object{
				NodeID: nodeId,
				Size:   1,
				Roles:  map[uint64]*RoleInfo{},
			}

			obj.Roles[arg.GetRoleID()] = &RoleInfo{
				UserID:      arg.GetUserID(),
				RoleID:      arg.GetRoleID(),
				Game:        cluster.PeerID(arg.GetGame()),
				BattleAttrs: map[int32]int32{},
				Skills:      []*Skill{},
			}

			//拉取角色信息
			obj.getRoleInfo()
		} else {
			_team := team.TeamMgr.GetTeam(arg.GetTeamID())
			if _team != nil {

				_team.Status = com.TeamStatus_Battle
				if _team.GetRoleCount() > 1 { //大于一个人需要队员同意

					_team.NewFightInfo(arg.GetBattleLevelType())
				} else if _team.GetRoleCount() == 1 {

					obj := &Object{
						NodeID: nodeId,
						Size:   1,
						TeamID: _team.TeamID,
						Roles:  map[uint64]*RoleInfo{},
					}

					for _, r := range _team.GetRoles() {
						obj.Roles[r.RoleID] = &RoleInfo{
							UserID:      r.UserID,
							RoleID:      r.RoleID,
							Game:        r.Game,
							BattleAttrs: map[int32]int32{},
							Skills:      []*Skill{},
						}
					}

					//拉取角色信息
					obj.getRoleInfo()
				}
			}

		}
	} else if arg.GetMsgType() == match_cancel {
		resp := &cs_msg.MatchToC{
			MsgType: cs_msg.MatchType(cs_msg.MatchType_Cancel).Enum(),
		}

		_matchObj := MatchMgr.RoleToObj[arg.GetRoleID()]
		if _matchObj != nil {
			//todo
			queue := MatchMgr.GetMatchQueue(1, 10)
			if queue != nil {
				obj := queue.GetQueueOjb(_matchObj.NodeID)
				if obj != nil {
					if obj.TeamID != 0 {
						_team := team.TeamMgr.GetTeam(obj.TeamID)
						_team.Status = com.TeamStatus_Safe
						for _, r := range _team.GetRoles() {
							r.SendToClient(resp)
						}
					} else {
						for _, r := range obj.Roles {
							com.SendToClient(r.Game, r.UserID, resp)
						}
					}
					queue.DelQueue(_matchObj.NodeID)
					for _, r := range obj.Roles {
						delete(MatchMgr.RoleToObj, r.RoleID)
					}
				}
			}
		}
	}

}

func (this *Object) getRoleInfo() {
	_mutilCall := mutilCall.NewMutilCall()

	for _, r := range this.Roles {
		req := &ss_rpc.GetRoleInfoReq{
			UserID: proto.String(r.UserID),
			RoleID: proto.Uint64(r.RoleID),
		}
		_mutilCall.Add(r.Game, req, transaction.TransTimeoutMs)
	}

	respAllOk := func(results []mutilCall.Result) bool {
		for _, v := range results {
			resp := v.Ret.(*ss_rpc.GetRoleInfoResp)
			req := v.Req.(*ss_rpc.GetRoleInfoReq)
			if !resp.GetOk() {
				node_team.Infoln("getRoleInfo fail", req.GetUserID(), req.GetRoleID())
				return false
			}
		}

		return true
	}

	_mutilCall.AnyFailOrAllSuccess(func(results []mutilCall.Result, err error) {
		if err != nil || !respAllOk(results) {
			//失败
			this.matchQueueFail()
			node_team.Errorln("getRoleInfo err or anyRole fail", err)
		} else {
			for _, v := range results {
				resp := v.Ret.(*ss_rpc.GetRoleInfoResp)
				role := this.Roles[resp.GetRole().GetRoleID()]

				role.Name = resp.GetRole().GetName()
				role.Level = resp.GetRole().GetLevel()
				role.Portrait = resp.GetRole().GetPortrait()
				role.Outline = resp.GetRole().GetOutline()
				role.Face = resp.GetRole().GetFace()
				role.Hair = resp.GetRole().GetHair()
				role.HairColor = resp.GetRole().GetHairColor()
				role.EyeColor = resp.GetRole().GetEyeColor()
				role.Cloth = resp.GetRole().GetCloth()
				role.ClothColor = resp.GetRole().GetClothColor()

				role.Weapon1 = resp.GetRole().GetWeapon1()
				role.Weapon2 = resp.GetRole().GetWeapon2()
				for _, s := range resp.GetRole().GetSkills() {
					role.Skills = append(role.Skills, &Skill{
						SkillID:     s.GetSkillID(),
						SkillLevel:  s.GetSkillLevel(),
						SkillType:   s.GetSkillType(),
						SpecialStar: s.GetSpecialStar(),
					})
				}
				for _, b := range resp.GetRole().GetBattleAttrs() {
					role.BattleAttrs[b.GetIndex()] = b.GetValue()
				}
			}

			//成功
			this.matchQueueOK()
		}
	})
}

func (this *Object) matchQueueOK() {
	resp := &cs_msg.MatchToC{
		MsgType: cs_msg.MatchType(cs_msg.MatchType_Request).Enum(),
	}

	for _, r := range this.Roles {
		MatchMgr.RoleToObj[r.RoleID] = this
		com.SendToClient(r.Game, r.UserID, resp)
	}

	if this.Size >= com.MatchRoleCount {
		objs := []*Object{
			0: this,
		}
		CreatRoom(objs)
	} else {
		//todo
		queue := MatchMgr.GetMatchQueue(1, 10)
		if queue != nil {
			queue.AddQueue(this.NodeID, this)
		}
	}
}

func (this *Object) matchQueueFail() {
	resp := &cs_msg.MatchToC{
		MsgType: cs_msg.MatchType(cs_msg.MatchType_Fail).Enum(),
	}

	for _, r := range this.Roles {
		com.SendToClient(r.Game, r.UserID, resp)
	}

	if this.TeamID != 0 {
		_team := team.TeamMgr.GetTeam(this.TeamID)
		_team.Status = com.TeamStatus_Safe
	}

}

func init() {
	cluster.Register(&ss_msg.Match{}, func(session kendynet.StreamSession, msg proto.Message) {
		onMatch(session, msg)
	})
}
